﻿using HlgSiemensCommunication;
using MiniExcelLibs;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace HlgSiemensFrmMain
{
    public partial class FrmMain : UIForm
    {
        static HlgSiemensCommunication.SiemensS7Client _SiemensS7 = null;
        private readonly string pathfile = AppDomain.CurrentDomain.BaseDirectory + "\\PLC\\PLCInfo.xlsx";
        private readonly string pathfileplc = AppDomain.CurrentDomain.BaseDirectory + "\\PLC\\PLC.xlsx";
        static List<PLCInfos> _dataSource = new List<PLCInfos>();

        public FrmMain()
        {
            InitializeComponent();

            Load += Form1_Load;
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            string path = AppDomain.CurrentDomain.BaseDirectory + "\\PLC";
            bool flag = !Directory.Exists(path);
            if (flag)
            {
                Directory.CreateDirectory(path);
            }

            bool flag2 = !File.Exists(this.pathfile);
            if (flag2)
            {
                MiniExcel.SaveAs(this.pathfile, new List<PLCInfos>(), true, "Sheet1", ExcelType.UNKNOWN, null, false);
            }

            bool flagPLC = !File.Exists(this.pathfileplc);
            if (flagPLC)
            {
                MiniExcel.SaveAs(this.pathfileplc, new List<PLCInfos>(), true, "Sheet1", ExcelType.UNKNOWN, null, false);
            }

            this.Init(this.pathfile);


            var plcCurrent = (from x in MiniExcel.Query<PLC>(pathfileplc, null, ExcelType.UNKNOWN, "A1", null)
                              select x).FirstOrDefault<PLC>();

            if (plcCurrent != null)
            {
                txt_Ip.Text = plcCurrent.Ip;
                txt_Port.IntValue = plcCurrent.Port;
            }
        }

        private void Init(string pathfile)
        {
            List<PLCInfos> dataSource = (from x in MiniExcel.Query<PLCInfos>(pathfile, null, ExcelType.UNKNOWN, "A1", null)
                                         select x).ToList<PLCInfos>();


            _dataSource.Clear();
            _dataSource.AddRange(dataSource);

            this.uiDataGridView1.DataSource = _dataSource;

            for (int i = 0; i < this.uiDataGridView1.Columns.Count; i++)
            {
                this.uiDataGridView1.Columns[i].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                this.uiDataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;

                this.uiDataGridView1.Columns[i].Width = 200;
            }

            this.uiDataGridView1.Refresh();
        }

        private void btn_Conn_Click(object sender, EventArgs e)
        {
            try
            {
                if (!string.IsNullOrEmpty(txt_Ip.Text) && !string.IsNullOrEmpty(txt_Port.Text))
                {
                    _SiemensS7 = _SiemensS7 ?? new HlgSiemensCommunication.SiemensS7Client(txt_Ip.Text, Convert.ToInt32(txt_Port.Text));
                    _SiemensS7.Conn();
                    if (!_SiemensS7.IsConnection)
                    {
                        ShowErrorTip("Connection Error");
                        _SiemensS7 = null;
                    }
                    else
                    {
                        btn_Conn.Enabled = false;
                        ShowSuccessTip("Connection Success");
                    }
                }
                else
                    ShowWarningTip("请输入IP Port");

            }
            catch (Exception ex)
            {
                ShowErrorTip(ex.Message);
            }
        }

        private void btn_Add_Click(object sender, EventArgs e)
        {
            _dataSource.Add(new PLCInfos()
            {
                DB = "DB1.DDD2.0",
                DBName = "---",
                DBValueType = "String",
                DBLength = 20,
                DBValue = 0,
                DBType = "DB"

            });

            SearchData();
        }

        private void SearchData()
        {
            this.uiDataGridView1.DataSource = _dataSource.ToList();
            for (int i = 0; i < this.uiDataGridView1.Columns.Count; i++)
            {
                this.uiDataGridView1.Columns[i].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                this.uiDataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;

                this.uiDataGridView1.Columns[i].Width = 200;
            }
            this.uiDataGridView1.Refresh();
        }

        private void btn_Delete_Click(object sender, EventArgs e)
        {
            try
            {
                var index = this.uiDataGridView1.CurrentRow?.Index;
                if (index == null)
                    return;

                var current = (uiDataGridView1.DataSource as List<PLCInfos>)[index.Value];
                _dataSource.Remove(current);
                SearchData();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        private void btn_Save_Click(object sender, EventArgs e)
        {
            using (FileStream fileStream = File.Create(this.pathfile))
            {
                fileStream.SaveAs(_dataSource, true, "Sheet1", ExcelType.XLSX, null);
            }

            using (FileStream fileStream = File.Create(this.pathfileplc))
            {
                List<PLC> pLC = new List<PLC>()
                {
                    new PLC(){
                    Ip = txt_Ip.Text,
                    Port = txt_Port.IntValue
                    }
                };

                fileStream.SaveAs(pLC, true, "Sheet1", ExcelType.XLSX, null);
            }
        }

        private void btn_DisConn_Click(object sender, EventArgs e)
        {
            if (_SiemensS7 != null && !_SiemensS7.IsConnection)
            {
                _SiemensS7.Close();
                _SiemensS7 = null;
                ShowSuccessTip("DisConnection Success");
                btn_Conn.Enabled = true;
            }
            else
            {
                ShowWarningTip("Error Operating");
                btn_Conn.Enabled = true;
            }
        }

        private void btn_Refresh_Click(object sender, EventArgs e)
        {
            this.Init(this.pathfile);
        }

        private void btn_Read_Click(object sender, EventArgs e)
        {
            try
            {
                var index = this.uiDataGridView1.CurrentRow.Index;
                var current = (uiDataGridView1.DataSource as List<PLCInfos>)[index];
                if (current == null)
                {
                    ShowWarningTip("【Error Operating】");
                    return;
                }

                if (_SiemensS7 == null || !_SiemensS7.IsConnection)
                {
                    ShowWarningTip("【PLC NO Connection】 Error Operating");
                }
                else
                {
                    var type = Enum.TryParse<siemensDBType>(current.DBValueType.ToUpper(), out siemensDBType result);
                    var output = string.Empty;
                    if (!type)
                    {
                        ShowWarningTip("No DataType");
                        return;
                    }
                    var typeDBtype = Enum.TryParse<DBtype>(current.DBType.ToUpper(), out DBtype typeDBtyperesult);
                    if (!typeDBtype)
                    {
                        ShowWarningTip("No DataType");
                        return;
                    }
                    switch (result)
                    {
                        case siemensDBType.BOOL:
                            output = _SiemensS7.ReadBool(current.DB, typeDBtyperesult).ToString();
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】当前值【{output} 】  {DateTime.Now}");
                            break;
                        case siemensDBType.FLOAT:
                            output = _SiemensS7.ReadFloat(current.DB, typeDBtyperesult).ToString();
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】当前值【{output} 】  {DateTime.Now}");
                            break;
                        case siemensDBType.STRING:
                            output = _SiemensS7.ReadString(current.DB, current.DBLength, true, typeDBtyperesult).ToString();
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】当前值【{output} 】  {DateTime.Now}");
                            break;
                        case siemensDBType.UINT16:
                            output = _SiemensS7.ReadUint16(current.DB, typeDBtyperesult).ToString();
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】当前值【{output} 】  {DateTime.Now}");
                            break;
                        case siemensDBType.INT16:
                            output = _SiemensS7.ReadInt16(current.DB, typeDBtyperesult).ToString();
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】当前值【{output} 】  {DateTime.Now}");
                            break;
                        case siemensDBType.BYTE:
                            output = _SiemensS7.ReadByte(current.DB, typeDBtyperesult).ToString();
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】当前值【{output} 】  {DateTime.Now}");
                            break;
                        case siemensDBType.STRINGARRAY:
                            output = _SiemensS7.ReadStringArray(current.DB, 20, typeDBtyperesult).ToString();
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】当前值【{output} 】  {DateTime.Now}");
                            break;
                    }

                    _dataSource.Where(x => x.DB == current.DB).FirstOrDefault().DBValue = output;
                    uiDataGridView1.Refresh();

                    txt_Infos.AppendText("\r\n");
                    txt_Infos.ScrollToCaret();
                }
            }
            catch (Exception ex)
            {
                ShowErrorTip(ex.Message);
            }
        }

        private void btn_Write_Click(object sender, EventArgs e)
        {
            try
            {
                var index = this.uiDataGridView1.CurrentRow.Index;
                var current = (uiDataGridView1.DataSource as List<PLCInfos>)[index];
                if (current == null)
                {
                    ShowWarningTip("Error Operating");
                    return;
                }

                if (_SiemensS7 == null || !_SiemensS7.IsConnection)
                {
                    ShowWarningTip("【PLC NO Connection】 Error Operating");
                }
                else
                {
                    var type = Enum.TryParse<siemensDBType>(current.DBValueType.ToUpper(), out siemensDBType result);
                    var output = true;
                    if (!type)
                    {
                        ShowWarningTip("No DataType");
                        return;
                    }
                    var typeDBtype = Enum.TryParse<DBtype>(current.DBType.ToUpper(), out DBtype typeDBtyperesult);
                    if (!typeDBtype)
                    {
                        ShowWarningTip("No DataType");
                        return;
                    }

                    switch (result)
                    {
                        case siemensDBType.BOOL:

                            var flag = bool.TryParse(current.DBValueType.ToString(), out bool iresult);
                            if (flag)
                            {
                                output = _SiemensS7.WriteBool(current.DB, iresult, typeDBtyperesult);
                                txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】写入状态【{output} 】  {DateTime.Now}");
                            }
                            else
                            {
                                int num = Convert.ToInt16(current.DBValue);
                                output = _SiemensS7.WriteBool(current.DB, num > 0, typeDBtyperesult);
                                txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】写入状态【{output} 】  {DateTime.Now}");
                            }
                            break;
                        case siemensDBType.FLOAT:
                            output = _SiemensS7.WriteFloat(current.DB, float.Parse(current.DBValue.ToString()), typeDBtyperesult);
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】写入状态【{output} 】  {DateTime.Now}");
                            break;
                        case siemensDBType.STRING:
                            output = _SiemensS7.WriteString(current.DB, current.DBValue.ToString(), current.DBLength, typeDBtyperesult);
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】写入状态【{output} 】  {DateTime.Now}");
                            break;
                        case siemensDBType.UINT16:
                            output = _SiemensS7.WriteUint16(current.DB, ushort.Parse(current.DBValue.ToString()), typeDBtyperesult);
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】写入状态【{output} 】  {DateTime.Now}");

                            break;
                        case siemensDBType.INT16:
                            output = _SiemensS7.WriteInt16(current.DB, short.Parse(current.DBValue.ToString()), typeDBtyperesult);
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】当前值【{output} 】  {DateTime.Now}");
                            break;
                        case siemensDBType.BYTE:
                            output = _SiemensS7.WriteByte(current.DB, byte.Parse(current.DBValue.ToString()), typeDBtyperesult);
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】当前值【{output} 】  {DateTime.Now}");
                            break;
                        case siemensDBType.STRINGARRAY:
                            output = _SiemensS7.WriteStringArray(current.DB, current.DBValue?.ToString(), current.DBLength, typeDBtyperesult);
                            txt_Infos.AppendText($"DB【{current.DB}】  描述【{current.DBName}】写入状态【{output} 】  {DateTime.Now}");
                            break;
                    }

                    //_dataSource.Where(x => x.DB == current.DB).FirstOrDefault().DBValue = output;
                    //uiDataGridView1.Refresh();

                    txt_Infos.AppendText("\r\n");
                    txt_Infos.ScrollToCaret();
                }
            }
            catch (Exception ex)
            {
                ShowErrorTip(ex.Message);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var output = _SiemensS7.ReadValue(new List<InputSiemensParams>()
            {
                 new InputSiemensParams  ()
                 {
                      DB="DB0.DBB4.0",
                       DBtype=DBtype.I,
                        ItemType=SiemensDataType.Int16,
                 }
            });

            _SiemensS7.WriteValue(new List<InputSiemensParams>()
            {
                 new InputSiemensParams  ()
                 {
                      DB="DB0.DBB4.0",
                       DBtype=DBtype.I,
                        ItemType=SiemensDataType.Int16,
                         WriteValue=10086
                 }
            });

        }
    }

    public class PLCInfos
    {
        [DisplayName("DB地址")]
        public string DB { get; set; }

        [DisplayName("DB数据类型")]
        public string DBValueType { get; set; }

        [DisplayName("DB块类型")]
        public string DBType { get; set; }

        [DisplayName("DB点位描述")]
        public string DBName { get; set; }

        [DisplayName("字符串长度")]
        public int DBLength { get; set; }

        [DisplayName("当前值")]
        public object DBValue { get; set; }
    }

    public class PLC
    {
        public string Ip { get; set; }
        public int Port { get; set; }
    }

    public enum siemensDBType
    {
        BOOL,
        FLOAT,
        STRING,
        UINT16,
        INT16,
        BYTE,
        STRINGARRAY
    }
}
